<?php
namespace Swork\Server;

use Swork\Server\Task\TaskManager;
use Swork\Service;

/**
 * 任务管理器
 */
class Tasker
{
    /**
     * 推送任务
     * @param string $cls 任务所在CLASS
     * @param string $name 执行方法的名称
     * @param array $args 执行方法的参数
     * @param int $timeout 执行超时时间（单位秒）
     * @param int $delay 延时执行（单位秒）
     */
    public static function deliver(string $cls, string $name, array $args = [], int $timeout = 10, int $delay = 0)
    {
        //类名前补斜线
        if (strpos($cls, '\\') !== 0)
        {
            $cls = "\\$cls";
        }

        //组装数据
        $info = [
            'cls' => $cls,
            'name' => $name,
            'args' => $args,
            'timeout' => $timeout,
        ];

        //判断是否有延时
        if ($delay > 0)
        {
            \Swoole\Timer::after($delay * 1000, function () use ($info) {
                self::sendTask($info);
            });
        }
        else
        {
            self::sendTask($info);
        }
    }

    /**
     * 协程方式推送任务
     * @param string $cls 任务所在CLASS
     * @param string $name 执行方法的名称
     * @param array $args 执行方法的参数
     * @param int $timeout 执行超时时间（单位秒）
     * @return mixed
     */
    public static function deliverCo(string $cls, string $name, array $args = [], int $timeout = 10)
    {
        //类名前补斜线
        if (strpos($cls, '\\') !== 0)
        {
            $cls = "\\$cls";
        }

        //组装数据
        $info = [
            'cls' => $cls,
            'name' => $name,
            'args' => $args,
            'timeout' => $timeout,
        ];
        $taskManager = new TaskManager(Service::$env);
        $data = $taskManager->decorateData($info);

        //发起任务
        return Service::$server->taskCo([$data], $timeout);
    }

    /**
     * 向线程发送任务
     * @param array $info 任务内容
     */
    private static function sendTask(array $info)
    {
        //投递任务
        if (Service::$server->taskworker || Service::$server->worker_id != 0)
        {
            $data = [
                'act' => 'DeliverTask',
                'args' => $info
            ];
            Service::$server->sendMessage(serialize($data), 0);
        }
        else
        {
            Service::$taskManager->deliverTask($info);
        }
    }
}


